#pragma once
#include <iostream>
#include <memory>
#include <functional>
#include "Socket.hpp"
#include "InetAddr.hpp"
#include "Log.hpp"
#include "Protocol.hpp"

using namespace log_ns;
using namespace socket_ns;

using process_t = std::function<std::shared_ptr<Response>(std::shared_ptr<Request>)>;

class IOService
{
public:
    IOService(process_t process)
        :_process(process)
    {
    }
    ~IOService()
    {
    }
    void IOExcute(SockSPtr sockfd, InetAddr &addr)
    {
        std::string packagestream;
        while (true)
        {
            //1. 负责读取
            ssize_t n = sockfd->Recv(&packagestream);
            if (n <= 0)
            {
                LOG(INFO, "client %s quit or recv error",addr.AddrStr());
                break;
            }
            //能保证读到一个完整的报文吗 : 不能
            //2. 报文解析
            std::string package = Decode(packagestream);
            if(package.empty())
                continue;
            //走到这里，一定能读到一个完整的报文
            //3. 请求反序列化
            auto req = Factory::BuidRequestDefault();
            req->Deserialize(package);

            //4. 业务处理
            auto resp = _process(req);

            //5. 应答序列化
            std::string respjson;
            resp->Serialize(&respjson);

            //6. 添加报头
            respjson = Encode(respjson);

            //7. 发送应答
            sockfd->Send(respjson);
        }
    }

private:
    process_t _process;
};

